home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 9 / Night Owl CD-ROM (NOPV9) (Night Owl Publisher) (1993).ISO / 009a / snpd0493.zip / DBL2LONG.C < prev    next >
C/C++ Source or Header  |  1993-04-05  |  2KB  |  65 lines

  1. /*
  2. **  DBL2LONG.C - Functions to round doubles to longs
  3. **  Public domain by Ross G. Cottrell, June 1992
  4. */
  5.  
  6. #include <float.h>
  7. #include <limits.h>
  8. #include <assert.h>
  9.  
  10. /* Assume IEEE doubles, little-endian CPU, 32-bit 2's complement longs. */
  11. /* (Actually, the assumptions made here aren't quite that gross.)       */
  12.  
  13. unsigned long dbl2ulong(double t)
  14. {
  15.       assert(1 == FLT_ROUNDS);
  16.       t += 1.0 / DBL_EPSILON;
  17.       return *(unsigned long *)&t;
  18. }
  19.  
  20. long dbl2long(double t)
  21. {
  22.       assert(1 == FLT_ROUNDS);
  23.       t += 1.0 / DBL_EPSILON + 2.0 * (LONG_MAX + 1.0);
  24.       return *(long *)&t;
  25. }
  26.  
  27. #ifdef TEST
  28.  
  29. #include <stdlib.h>
  30. #include <math.h>
  31.  
  32. int main(int argc, char **argv)
  33. {
  34.       while (*++argv)
  35.       {
  36.             printf("'%s', as a long: %ld, as an unsigned long: %lu\n",
  37.                   *argv, dbl2long(atof(*argv)), dbl2ulong(atof(*argv)));
  38.       }
  39.       return 0;
  40. }
  41.  
  42. #endif /* TEST */
  43.  
  44. /*
  45.  
  46. EXPLANATION:
  47.  
  48. The offset of 1.0/DBL_EPSILON forces the least significant bit of the
  49. mantissa to represent the integer 1.  This may not work on all formats of
  50. doubles, but I think it's a safe bet for IEEE compliant doubles, and any
  51. other floating point format with a radix of 2.  When this offset is added,
  52. the number should be rounded to the nearest representable value.  The
  53. assertion that FLT_ROUNDS has the value of 1 is an attempt to guarantee
  54. this.  You might check your float.h; if this isn't #defined as a constant 1
  55. you should investigate how to ensure that it will always round to the
  56. nearest.  If it is #defined as 1 you can safely rip out the assertions.  The
  57. addition of 2.0*(LONG_MAX+1.0) for the signed long is to prevent the the MSB
  58. of the mantissa being borrowed for negative inputs - if this happened, the
  59. exponent would change and the LSB of the mantissa would no longer be worth
  60. 1.  This offset would be perfectly okay to use with the unsigned longs too
  61. but it's unnecessary for them, unless you want to get the answer correct
  62. modulo 2^^32 for negatives.
  63.  
  64. */
  65.